package entity

import (
	"time"

	"github.com/google/uuid"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
)

// AdminRole 管理员角色类型
type AdminRole string

const (
	AdminRoleSuper AdminRole = "super" // 超级管理员
	AdminRoleAdmin AdminRole = "admin" // 普通管理员
)

// Admin 管理员用户模型
type Admin struct {
	ID        uuid.UUID  `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()"` // 管理员ID
	Username  string     `gorm:"column:username;not null;size:50;uniqueIndex"`    // 管理员用户名
	Password  string     `gorm:"column:password;not null;size:255"`               // 加密后的密码
	Email     string     `gorm:"column:email;size:100;uniqueIndex"`               // 邮箱
	Role      AdminRole  `gorm:"column:role;not null;default:'admin'"`            // 管理员角色
	IsActive  bool       `gorm:"column:is_active;default:true"`                   // 是否激活
	LastLogin *time.Time `gorm:"column:last_login"`                               // 最后登录时间
	CreatedAt time.Time  `gorm:"autoCreateTime"`
	UpdatedAt time.Time  `gorm:"autoUpdateTime"`
}

// TableName specifies the table name for the Admin model.
func (Admin) TableName() string {
	return "admins"
}

// BeforeCreate 在创建之前的钩子，加密密码
func (a *Admin) BeforeCreate(tx *gorm.DB) error {
	if a.Password != "" {
		hashedPassword, err := bcrypt.GenerateFromPassword([]byte(a.Password), bcrypt.DefaultCost)
		if err != nil {
			return err
		}
		a.Password = string(hashedPassword)
	}
	return nil
}

// BeforeUpdate 在更新之前的钩子，如果密码有变更则加密
func (a *Admin) BeforeUpdate(tx *gorm.DB) error {
	// 只有在密码字段被修改时才重新加密
	if tx.Statement.Changed("Password") && a.Password != "" {
		hashedPassword, err := bcrypt.GenerateFromPassword([]byte(a.Password), bcrypt.DefaultCost)
		if err != nil {
			return err
		}
		a.Password = string(hashedPassword)
	}
	return nil
}

// CheckPassword 验证密码
func (a *Admin) CheckPassword(password string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(a.Password), []byte(password))
	return err == nil
}

// IsSuper 检查是否为超级管理员
func (a *Admin) IsSuper() bool {
	return a.Role == AdminRoleSuper
}

// UpdateLastLogin 更新最后登录时间
func (a *Admin) UpdateLastLogin() {
	now := time.Now()
	a.LastLogin = &now
}

// GetID 实现 Authenticatable 接口
func (a *Admin) GetID() uuid.UUID {
	return a.ID
}

// GetUsername 实现 Authenticatable 接口
func (a *Admin) GetUsername() string {
	return a.Username
}
